﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Aliyeye.Car.Net.Utility
{
    public static class ColorExtension
    {
        public static Color Lighten(this Color owner, byte amount)
        {
            double l = ((double)amount) / 255D;
            // below code is incorrect
            //int r, g, b;

            //if (owner.R + amount > 255)
            //{
            //    amount = (byte)(255 - owner.R);
            //}
            //if (owner.G + amount > 255)
            //{
            //    amount = (byte)(255 - owner.G);
            //}
            //if (owner.B + amount > 255)
            //{
            //    amount = (byte)(255 - owner.B);
            //}


            //r = owner.R + amount * owner.R / 255;
            //g = owner.G + amount * owner.G / 255;
            //b = owner.B + amount * owner.B / 255;

            //Color ret = Color.FromArgb(r > 255 ? 255 : r, g > 255 ? 255 : g, b > 255 ? 255 : b);

            HSL hsl = owner.GetHSL();

            hsl.L += l;

            return hsl.GetColor();
        }

        public static HSL GetHSL(this Color owner)
        {
            HSL ret = new HSL();
            ret.H = owner.GetHue() / 360.0;
            ret.S = owner.GetSaturation();
            ret.L = owner.GetBrightness();
            return ret;
        }
    }

    public class HSL
    {
        public HSL()
        {
            _h = 0;
            _s = 0;
            _l = 0;
        }

        double _h;
        double _s;
        double _l;

        public double H
        {
            get { return _h; }
            set
            {
                _h = value;
                _h = _h > 1 ? 1 : _h < 0 ? 0 : _h;
            }
        }

        public double S
        {
            get { return _s; }
            set
            {
                _s = value;
                _s = _s > 1 ? 1 : _s < 0 ? 0 : _s;
            }
        }

        public double L
        {
            get { return _l; }
            set
            {
                _l = value;
                _l = _l > 1 ? 1 : _l < 0 ? 0 : _l;
            }
        }

        public Color GetColor()
        {
            double h = this.H;
            double sl = this.S;
            double l = this.L;

            double v;
            double r, g, b;

            r = l;   // default to gray
            g = l;
            b = l;
            v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
            if (v > 0)
            {
                double m;
                double sv;
                int sextant;
                double fract, vsf, mid1, mid2;

                m = l + l - v;
                sv = (v - m) / v;
                h *= 6.0;
                sextant = (int)h;
                fract = h - sextant;
                vsf = v * sv * fract;
                mid1 = m + vsf;
                mid2 = v - vsf;
                switch (sextant)
                {
                    case 0:
                        r = v;
                        g = mid1;
                        b = m;
                        break;
                    case 1:
                        r = mid2;
                        g = v;
                        b = m;
                        break;
                    case 2:
                        r = m;
                        g = v;
                        b = mid1;
                        break;
                    case 3:
                        r = m;
                        g = mid2;
                        b = v;
                        break;
                    case 4:
                        r = mid1;
                        g = m;
                        b = v;
                        break;
                    case 5:
                        r = v;
                        g = m;
                        b = mid2;
                        break;
                }
            }
            Color rgb = Color.FromArgb(Convert.ToByte(r * 255.0f),
                Convert.ToByte(g * 255.0f),
                Convert.ToByte(b * 255.0f));
            return rgb;

            //double r = 0, g = 0, b = 0;
            //double temp1, temp2;

            //if (hsl.L == 0)
            //{
            //    r = g = b = 0;
            //}
            //else
            //{
            //    if (hsl.S == 0)
            //    {
            //        r = g = b = hsl.L;
            //    }
            //    else
            //    {
            //        temp2 = ((hsl.L <= 0.5) ? hsl.L * (1.0 + hsl.S) : hsl.L + hsl.S - (hsl.L * hsl.S));
            //        temp1 = 2.0 * hsl.L - temp2;

            //        double[] t3 = new double[] { hsl.H + 1.0 / 3.0, hsl.H, hsl.H - 1.0 / 3.0 };
            //        double[] clr = new double[] { 0, 0, 0 };
            //        for (int i = 0; i < 3; i++)
            //        {
            //            if (t3[i] < 0)
            //                t3[i] += 1.0;
            //            if (t3[i] > 1)
            //                t3[i] -= 1.0;

            //            if (6.0 * t3[i] < 1.0)
            //                clr[i] = temp1 + (temp2 - temp1) * t3[i] * 6.0;
            //            else if (2.0 * t3[i] < 1.0)
            //                clr[i] = temp2;
            //            else if (3.0 * t3[i] < 2.0)
            //                clr[i] = (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - t3[i]) * 6.0);
            //            else
            //                clr[i] = temp1;
            //        }
            //        r = clr[0];
            //        g = clr[1];
            //        b = clr[2];
            //    }
            //}

            //return Color.FromArgb((int)(255 * r), (int)(255 * g), (int)(255 * b));
        }
    }
}
